Windpark Kelmarsh (2016) - 12.5 MW

Reliability Evaluation

Author

Jorge A. Thomas

Published

Invalid Date

Read parquet files

Show the code
```{python}
#| label: Read-Data
tstatus = pl.read_parquet(f"{folder_path_interim}Kelmarsh_Turbines_Status_20160114_20230109_n385133_cols12.parquet")

tstatus
```
shape: (385_133, 12)
Timestamp start Timestamp end Status Code Message Comment Service contract category IEC category wt Global contract category Custom contract category Duration
datetime[μs, UTC] datetime[μs, UTC] str i64 str str str str str str str duration[μs]
2016-01-14 19:28:03 UTC 2016-01-23 14:36:32 UTC "Stop" 111 "Emergency stop nacelle" null "Emergency stop switch (Nacelle… "Forced outage" "T01" null null 8d 19h 8m 29s
2016-01-14 19:28:03 UTC 2016-01-14 19:38:03 UTC "Warning" 5720 "Brake accumulator defect" null "Warnings (27)" null "T01" null null 10m
2016-01-14 19:28:05 UTC 2016-01-23 11:27:46 UTC "Informational" 3835 "Cable panel breaker open" null "Warnings (27)" null "T01" null null 8d 15h 59m 41s
2016-01-14 19:28:05 UTC 2016-01-23 11:27:46 UTC "Informational" 3830 "Supply circuit breaker earthed" null "Warnings (27)" "Full Performance" "T01" null null 8d 15h 59m 41s
2016-01-14 19:28:05 UTC 2016-01-23 14:09:18 UTC "Warning" 3870 "Overload transformer fan outle… null "Warnings (27)" "Full Performance" "T01" null null 8d 18h 41m 13s
2022-12-31 12:28:30 UTC null "Informational" 100160 "System test 3" null null "Technical Standby" "T06" null null null
2022-12-31 12:28:45 UTC null "Informational" 100180 "Run-up" null null "Technical Standby" "T06" null null null
2022-12-31 12:30:58 UTC null "Informational" 100190 "Mains connection" null null "Full Performance" "T06" null null null
2022-12-31 12:31:08 UTC null "Informational" 100200 "Mains run-up" null null "Full Performance" "T06" null null null
2022-12-31 12:31:38 UTC null "Informational" 100210 "Mains operation" null null "Full Performance" "T06" null null null

Filter Stop

Show the code
```{python}
#| label: Filter-Stops

stops = pl.sql(    
    """
    SELECT * EXCLUDE ("Custom contract category")    
    FROM tstatus
    WHERE "Status" = 'Stop'
    """).collect()
```

Filter Forced Outages

Show the code
```{python}
#| label: Filter-Forced-Outages

# Aggregate tables using SQL syntax
foutages = pl.sql(
    """
    SELECT * 
    FROM stops
    WHERE "IEC category" = 'Forced outage' 
    """).collect()

foutages = foutages.rename({"Duration":"TTR"})

# TTF
foutages = foutages.with_columns(
    (pl.col("Timestamp start").shift(-1) - pl.col("Timestamp end")).shift(1).alias("TTF")
    )

foutages = foutages.with_columns(
    pl.when(pl.col("TTF") < 0).then(None).otherwise(pl.col("TTF")).alias("TTF")
)

foutages
```
shape: (892, 12)
Timestamp start Timestamp end Status Code Message Comment Service contract category IEC category wt Global contract category TTR TTF
datetime[μs, UTC] datetime[μs, UTC] str i64 str str str str str str duration[μs] duration[μs]
2016-01-14 19:28:03 UTC 2016-01-23 14:36:32 UTC "Stop" 111 "Emergency stop nacelle" null "Emergency stop switch (Nacelle… "Forced outage" "T01" null 8d 19h 8m 29s null
2016-01-23 15:05:30 UTC 2016-01-23 15:06:42 UTC "Stop" 117 "Emergency stop base box" null "Emergency stop switch (Convert… "Forced outage" "T01" null 1m 12s 28m 58s
2016-01-24 16:51:17 UTC 2016-02-01 19:46:41 UTC "Stop" 3110 "Frequency converter error" null "Generator and Converter errors… "Forced outage" "T01" null 8d 2h 55m 24s 1d 1h 44m 35s
2016-02-11 14:36:37 UTC 2016-02-11 15:14:50 UTC "Stop" 3585 "Maximum grid frequency" null "External stop (grid) (4)" "Forced outage" "T01" null 38m 13s 9d 18h 49m 56s
2016-03-01 17:33:14 UTC 2016-03-01 17:35:14 UTC "Stop" 3000 "Frequency converter not ready" null "Generator and Converter errors… "Forced outage" "T01" null 2m 19d 2h 18m 24s
2022-05-11 14:08:43 UTC 2022-05-11 14:31:27 UTC "Stop" 555 "Pitch angle deviation" null "Pitch errors (18)" "Forced outage" "T06" "09 (Int) Fault" 22m 44s 2h 55m 14s
2022-05-12 02:37:43 UTC 2022-05-19 11:19:38 UTC "Stop" 555 "Pitch angle deviation" "Pitch fault - techs attended o… "Pitch errors (18)" "Forced outage" "T06" "09 (Int) Fault" 7d 8h 41m 55s 12h 6m 16s
2022-07-11 08:13:14 UTC 2022-07-11 13:48:21 UTC "Stop" 6530 "Anemometer defect" "Anemometer failed and replaced" "Sensor error (21)" "Forced outage" "T06" "09 (Int) Fault" 5h 35m 7s 52d 20h 53m 36s
2022-07-19 13:17:02 UTC 2022-07-19 18:11:27 UTC "Stop" 3151 "Max.temp.conv.inl.>perm.out.t." "Converters overheating due to … "Temperature error (22)" "Forced outage" "T06" "09 (Int) Fault" 4h 54m 25s 7d 23h 28m 41s
2022-11-02 17:39:07 UTC 2022-11-02 18:25:51 UTC "Stop" 21 "Manual stop - remote" null "Remote stop (30)" "Forced outage" "T06" "09 (Int) Fault" 46m 44s 105d 23h 27m 40s

Time Series for Binary Plot

Show the code
```{python}
#| label: Binary-Plot

dtstarts = foutages.select(["Timestamp start", "Status", "Message",  "wt"]).rename({"Timestamp start": "Timestamp"})
dtends = foutages.select(["Timestamp end", "Status", "Message",  "wt"]).with_columns(pl.lit("Start").alias("Status")).rename({"Timestamp end": "Timestamp"})

tstates = pl.concat([dtstarts, dtends]).sort(["wt", 'Timestamp'])

# tstates_ts = dtstarts.join(dtends, on="Timestamp", how="full").sort(["wt", 'Timestamp'])

tstates= tstates.with_columns(
    pl.when(pl.col("Status") == "Stop").then(0).otherwise(1).alias("State"),
    pl.col("Timestamp").dt.year().alias("Year")    
    )

tstates= tstates.with_columns(    
    (pl.col("wt") + " - " + pl.col("Year").cast(str)).alias("wt_Year")
    )

tstates
#TODO: remove missing years!
```
shape: (1_784, 7)
Timestamp Status Message wt State Year wt_Year
datetime[μs, UTC] str str str i32 i32 str
2016-01-14 19:28:03 UTC "Stop" "Emergency stop nacelle" "T01" 0 2016 "T01 - 2016"
2016-01-23 14:36:32 UTC "Start" "Emergency stop nacelle" "T01" 1 2016 "T01 - 2016"
2016-01-23 15:05:30 UTC "Stop" "Emergency stop base box" "T01" 0 2016 "T01 - 2016"
2016-01-23 15:06:42 UTC "Start" "Emergency stop base box" "T01" 1 2016 "T01 - 2016"
2016-01-24 16:51:17 UTC "Stop" "Frequency converter error" "T01" 0 2016 "T01 - 2016"
2022-07-11 13:48:21 UTC "Start" "Anemometer defect" "T06" 1 2022 "T06 - 2022"
2022-07-19 13:17:02 UTC "Stop" "Max.temp.conv.inl.>perm.out.t." "T06" 0 2022 "T06 - 2022"
2022-07-19 18:11:27 UTC "Start" "Max.temp.conv.inl.>perm.out.t." "T06" 1 2022 "T06 - 2022"
2022-11-02 17:39:07 UTC "Stop" "Manual stop - remote" "T06" 0 2022 "T06 - 2022"
2022-11-02 18:25:51 UTC "Start" "Manual stop - remote" "T06" 1 2022 "T06 - 2022"

Plot Square Signal

Show the code
```{python}
#| label: Square-Signal-Plot

import plotly.express as px

# Other line_shape options, or interpolation methods between given points:

# 'hv' step ends, equivalent to pyplot's post option;
# 'vh' step starts;
# 'hvh' step middles, x axis;
# 'vhv' step middles, y axis;
# 'spline' smooth curve between points;
# 'linear' line segments between points, default value for line_shape.

fig = px.line(tstates, x='Timestamp', y="State", line_shape='hv', facet_row="wt_Year", color="wt",
     title="Time / State Diagram for Kellmarsh Wind Turbines (2016-2022)",
     subtitle= "(0) Down Step=Forced outage (IEC), (1) Up Step=Start",
     labels={"Timestamp": "Time (UTC)", "State": "", "wt": ""},facet_row_spacing=0.01 )

# Update y-axis to show only 0 and 1 as labels
fig.update_yaxes(
    tickvals=[0, 1],  # Set tick values to 0 and 1
    ticktext=["", ""]  # Optional: Explicitly set tick text
)

fig.update_xaxes(matches=None, tickformat="%b"  )


# Update facet labels orientation and size
fig.for_each_annotation(lambda a: a.update(text=a.text.split("-")[-1],textangle=0, xanchor='left', x=-0.04))  # Make labels horizontal
fig.update_annotations(font_size=8)  # Reduce font size

fig.show()
```